﻿using System;
using System.Collections.Generic;
using System.Reflection;
using MedicService.Domain.Generic;
using MedicService.Domain.Print.Template;
using MedicService.Server.Factory.Print;

namespace MedicService.Domain.Print {

    public class PrintEntity {
        public PrintSettings Settings;
        public string Html;
        public string Type;

        protected void Init<E>(PrintTemplate<E> template) where E : PrintEntity{
            this.Settings = new PrintSettings {
                DoubleSided = template.DoubleSided != 0,
                Format = template.Format,
                MarginBottom = template.MarginBottom,
                MarginFooter = template.MarginFooter,
                MarginHeader = template.MarginHeader,
                MarginLeft = template.MarginLeft,
                MarginRight = template.MarginRight,
                MarginTop = template.MarginTop,
                Mode = template.Mode,
                Orientation = template.Orientation
            };
            this.Type = template.Type;
        }

        protected void Replace<E>(PrintTemplate<E> template, Entity entity) where E : PrintEntity {
            string text = template.Template;
            text = Replace(text, entity);
            this.Html = text;
        }

        protected string Replace(string text, Entity entity) {
            var name = entity.GetType().Name;
            Dictionary<String, String> subst = new Dictionary<string, string>();
            List<Substitution> publ = new SubstitutionFactory("(Condition IS NULL OR Condition='') AND (Context IS NULL OR Context='"+Type+"')").GetList(true);
            foreach (var substitution in publ) {
                string key = substitution.Alias + "=" + substitution.Value;
                if (!subst.ContainsKey(key)) {
                    subst[key] = substitution.Replace;
                } else {
                    //TODO: what can I do?
                }
            }
            HashSet<String> conditions = new HashSet<string>();
            FieldInfo[] fieldInfos = entity.GetType().GetFields();
            foreach (var info in fieldInfos) {
                string ns = info.FieldType.Namespace;
                if ("System".Equals(ns)) {
                    Type type = info.FieldType;
                    object v = info.GetValue(entity);
                    string value;
                    if (v is DateTime) {
                        value = ((DateTime)v).ToShortDateString();
                    } else {
                        value = "" + v;
                    }
                    conditions.Add(name + "." + info.Name + "=" + value);
                }
            }


            List<Substitution> current = new SubstitutionFactory("(Condition Like '%" + name + ".%') AND (Context IS NULL OR Context='" + Type + "')").GetList(true);
            foreach (var substitution in current) {
                string[] split = substitution.Condition.Split('[');
                bool add = true;
                for (int i = 1; i < split.Length; i++) {
                    string s = split[i];
                    string condition = s.Replace("]", "");
                    if (!conditions.Contains(condition)) {
                        add = false;
                        break;
                    }
                }
                if (add) {
                    string key = substitution.Alias + "=" + substitution.Value;
                    subst[key] = substitution.Replace;
                }
            }
            return Replace(text, entity, null, subst);
        }

        protected string Replace(string text, Entity entity, string name, Dictionary<string, string> subst) {
            if (!string.IsNullOrEmpty(text)) {
                if (name == null) {
                    name = entity.GetType().Name;
                }

                FieldInfo[] fieldInfos = entity.GetType().GetFields();

                foreach (var fieldInfo in fieldInfos) {
                    string ns = fieldInfo.FieldType.Namespace;
                    if ("System".Equals(ns)
                        || "MedicService.Domain.Directory.Simple".Equals(ns)
                        || "MedicService.Domain.Directory".Equals(ns)
                        || "MedicService.Domain".Equals(ns)) {
                        string fieldName = fieldInfo.Name;
                        string replace = "${" + name + "." + fieldName;
                        if (text.IndexOf(replace) >= 0) {
                            replace += "}";
                            Type type = fieldInfo.FieldType;
                            object v = fieldInfo.GetValue(entity);
                            string value;
                            if (v is DateTime) {
                                value = ((DateTime) v).ToShortDateString();
                            }else if (v is Entity) {
                                //------- start sub circle --------//
                                text = Replace(text, (Entity) v, name + "." + fieldName, subst);
                                //------- end sub circle -------//
                                value = null;
                            } else {
                                value = "" + v;
                            }
                            if (value != null) {
                                string key = name + "." + fieldName + "=" + value;
                                if (subst.ContainsKey(key)) {
                                    var val = subst[key];
                                    if (val.IndexOf("*") > 0) {
                                        val = val.Replace("*", value);
                                    }
                                    value = val;
                                } else {
                                    string key1 = name + "." + fieldName + "=*";
                                    if (subst.ContainsKey(key1)) {
                                        var val = subst[key1];
                                        if (val.IndexOf("*") > 0 && !string.IsNullOrEmpty(value)) {
                                            value = val.Replace("*", value);
                                        }
                                    }
                                }
                                text = text.Replace(replace, value);
                            }
                        }
                    }
                }
            }else {
                text = "<html></html>";
            }
            return text;
        }
    }
}